﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web.Http;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System.Data;
using System.Xml;
using RafikiSIS_Site.Libraries;
using System.Diagnostics;

namespace RafikiSIS_Site.Controllers
{
    [Authorize]
    [RoutePrefix("api")]
    public class APIController : ApiController
    {

        [Route("read/{commandname?}/{commandtype?}")]
        public JArray GetView( string commandname, string commandtype="view")
        {
            int UserID;
            
            JObject ReturnedDataSet;
            DataSet ConvertToJSON = new DataSet(commandname);
            Dictionary<string, string> QueryParameters = Request.GetQueryNameValuePairs().ToDictionary(kv => kv.Key, kv => kv.Value, StringComparer.OrdinalIgnoreCase);
            
            // Work toward solution for getting USERID without this DB fetch.
            //UserID = Convert.ToInt32(BasicFuncs.GetPersonIDFromUsername(User.Identity.Name));
            UserID = User.Identity.GetEntityID();

            ConvertToJSON.Tables.Add(DataFuncs.ReadDataFromDB(UserID, commandname, QueryParameters, commandtype));
            XmlDocument doc = new XmlDocument();
            doc = DataFuncs.WriteDataTable(ConvertToJSON.Tables[0]);

            string json = Newtonsoft.Json.JsonConvert.SerializeXmlNode(doc, Newtonsoft.Json.Formatting.Indented, true);
            if (json == "null")
            {
                return JArray.Parse("[]");
            }
            else
            {
                ReturnedDataSet = JObject.Parse(json);
            }


            // This set of conditionals checks two levels down to make sure an object exists at that level,
            // then returns everything from that level down, effectively stripping off the top level value.
            if (ReturnedDataSet != null)
            {
                if (ReturnedDataSet.First != null)
                {
                    if (ReturnedDataSet.First.First != null)
                    {
                        // Since the returned type must be an array, this checks to see if the jtoken is an array.  If not
                        // it creates an array and makes the jtoken the first object in it.
                        if (ReturnedDataSet.First.First.Type == JTokenType.Array)
                        {
                            return (JArray)ReturnedDataSet.First.First;
                        }
                        else
                        {
                            return new JArray(ReturnedDataSet.First.First);
                        }
                    }
                }
            }
            return null;
        }

        [Route("readnew/{commandname?}/{commandtype?}")]
        public JArray GetRead(string commandname, string commandtype = "view")
        {
            Stopwatch stopwatch = new Stopwatch();
            stopwatch.Start();
            int UserID;
            if (commandtype == "view")
                {
                    commandname = commandname.Replace(';', '.');
                }
           // commandname = commandname.Replace(';', '.');
            JObject ReturnedDataSet;
            DataSet ConvertToJSON = new DataSet(commandname);
            Dictionary<string, string> QueryParameters = Request.GetQueryNameValuePairs().ToDictionary(kv => kv.Key, kv => kv.Value, StringComparer.OrdinalIgnoreCase);

            // Work toward solution for getting USERID without this DB fetch.
            //UserID = Convert.ToInt32(BasicFuncs.GetPersonIDFromUsername(User.Identity.Name));
            UserID = User.Identity.GetEntityID();

            ConvertToJSON.Tables.Add(DataFuncs.ReadDataFromDB_New(UserID, commandname, QueryParameters, commandtype));
            
            XmlDocument doc = new XmlDocument();
            
            doc = DataFuncs.WriteDataTable(ConvertToJSON.Tables[0]);
           
            string json = Newtonsoft.Json.JsonConvert.SerializeXmlNode(doc, Newtonsoft.Json.Formatting.Indented, true);
            
            if (json == "null")
            {
                return JArray.Parse("[]");
            }
            else
            {
                ReturnedDataSet = JObject.Parse(json);
            }
            stopwatch.Stop();
            Console.Write(stopwatch.Elapsed);
            // This set of conditionals checks two levels down to make sure an object exists at that level,
            // then returns everything from that level down, effectively stripping off the top level value.
            if (ReturnedDataSet != null)
            {
                if (ReturnedDataSet.First != null)
                {
                    if (ReturnedDataSet.First.First != null)
                    {
                        // Since the returned type must be an array, this checks to see if the jtoken is an array.  If not
                        // it creates an array and makes the jtoken the first object in it.
                        if (ReturnedDataSet.First.First.Type == JTokenType.Array)
                        {
                            return (JArray)ReturnedDataSet.First.First;
                        }
                        else
                        {
                            return new JArray(ReturnedDataSet.First.First);
                        }
                    }
                }
            }
            
            return null;
        }


        /// <summary>
        /// Executes the WriteDataToDB stored procedure.  The full documentation of the stored procedure is in its definition
        /// in SQL Server.
        /// </summary>
        /// <param name="commandtype">The data type of the object whose attributes are going to be modified.
        ///                           Currently only supports Entity and EntityRelationship.</param>
        /// <param name="id">The ID of the object that will be modified. -1 means a new object.</param>
        /// <param name="models">The PUT data sent from the API call.  Should be JSON.</param>
        /// <returns></returns>
        [Route("write/{commandtype}/{id?}")]
        public JArray PutData( string commandtype, [FromBody]JObject models, string id="-1")
        {
            HttpRequestMessage my = Request;
            JArray UpdateData = JArray.Parse(models["models"].Value<String>());
            JToken outDataID;
            string DataID;
            Dictionary<string,string> Parameters = new Dictionary<string,string>();
            DataTable ResultSet;
            JObject ResultData;
            JToken ResultErrors;
            JToken ResultID;
            JArray ResultArray = new JArray();

            int UserID;

            // Work toward solution for getting USERID without this DB fetch.
            //UserID = User.Identity.GetEntityID();

            foreach (JObject TempJO in UpdateData)
            {
                Parameters.Clear();
                // Definitions for other data types will be added here later (probably in the format || trygetvalue...)
                if (TempJO.TryGetValue("EntityID", out outDataID))
                {
                    DataID = outDataID.Value<string>();
                }
                else
                {
                    DataID = "-1";
                    TempJO.Add("EntityID", "");
                }
                if(DataID != id)
                    throw new HttpResponseException(new HttpResponseMessage(HttpStatusCode.BadRequest));

                Parameters.Add("DataID", DataID);
                //Parameters.Add("RequestorEntityID",User.Identity.GetEntityID().ToString());
                Parameters.Add("RequestorEntityID", "0");
                Parameters.Add("DataTableType", commandtype);
                Parameters.Add("JSONData",JsonConvert.SerializeObject(TempJO));
                ResultSet = DataFuncs.ExecuteSQLsp("WriteDataToDB", Parameters);
                if (ResultSet.Columns.Contains("JSONData"))
                {
                    ResultData = JObject.Parse(ResultSet.Rows[0]["JSONData"].ToString());
                    if(ResultData.TryGetValue("DataError",out ResultErrors))
                    {
                        var resp = new HttpResponseMessage(HttpStatusCode.BadRequest)
                        {
                            //Content = new StringContent(string.Format("No product with ID = {0}", id)),
                            Content = new StringContent(new JArray(ResultData).ToString(),System.Text.Encoding.UTF8, "application/json"),
                            ReasonPhrase = ResultErrors.Value<string>()
                        };
                        throw new HttpResponseException(resp);
                    }
                    else // if there is no error
                    {
                        switch(commandtype)
                        {
                            case "Entity":
                                if(!ResultData.TryGetValue("EntityID",out ResultID) && ResultData.TryGetValue("DataID",out ResultID))
                                {
                                    ResultData.Remove("DataID");
                                    ResultData.Add("EntityID", ResultID);
                                }
                                break;
                            default:
                                break;
                        }
                        ResultArray.Add(ResultData);
                    }
                }
            }
            return ResultArray;
        }
    }
      
}
